package org.linlinjava.litemall.core.payment.paypal.service.impl;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.constant.LitemallWXMembershipLevelConstants;
import org.linlinjava.litemall.core.notify.AwsNotifyService;
import org.linlinjava.litemall.core.notify.NoticeHelper;
import org.linlinjava.litemall.core.notify.NotifyService;
import org.linlinjava.litemall.core.notify.PosPushSender;
import org.linlinjava.litemall.core.payment.DefaultCurType;
import org.linlinjava.litemall.core.payment.PaymentResponseCode;
import org.linlinjava.litemall.core.payment.paypal.config.PaypalPaymentIntent;
import org.linlinjava.litemall.core.payment.paypal.config.PaypalPaymentMethod;
import org.linlinjava.litemall.core.payment.paypal.config.PaypalPaymentState;
import org.linlinjava.litemall.core.payment.paypal.service.PaypalService;
import org.linlinjava.litemall.core.util.AdminCouponDateUtil;
import org.linlinjava.litemall.core.util.GeneratorUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.dto.LitemallAccountBookFormDto;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.CouponUserConstant;
import org.linlinjava.litemall.db.util.OrderHandleOption;
import org.linlinjava.litemall.db.util.OrderStatusUtil;
import org.linlinjava.litemall.db.util.OrderUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.paypal.api.payments.Amount;
import com.paypal.api.payments.DetailedRefund;
import com.paypal.api.payments.Details;
import com.paypal.api.payments.Payer;
import com.paypal.api.payments.Payment;
import com.paypal.api.payments.PaymentExecution;
import com.paypal.api.payments.RedirectUrls;
import com.paypal.api.payments.RefundRequest;
import com.paypal.api.payments.RelatedResources;
import com.paypal.api.payments.Sale;
import com.paypal.api.payments.Transaction;
import com.paypal.base.rest.APIContext;
import com.paypal.base.rest.PayPalRESTException;

import static org.linlinjava.litemall.db.beans.Constants.MEMBER_STATUS_INUSE;


/**
 * @author ：stephen
 * @date ：Created in 11/19/2019 2:02 PM
 * @description：paypeal服务
 */
@Service
public class GoodsPaypalServiceImpl implements PaypalService {
    private final Log logger = LogFactory.getLog(GoodsPaypalServiceImpl.class);

    @Autowired
    private APIContext apiContext;
    @Autowired
    private LitemallOrderService orderService;
    @Autowired
    private LitemallUserFormIdService formIdService;
    @Autowired
    private NotifyService notifyService;
    @Autowired
    private NoticeHelper noticeHelper;
    @Autowired
    private LitemallOrderGoodsService litemallOrderGoodsService;
    @Autowired
    private LitemallUserService userService;
    @Autowired
    private LitemallGoodsService goodsService;
    @Autowired
    private AwsNotifyService awsNotifyService;
    @Autowired
    private LitemallAdminService litemallAdminService;
    @Autowired
    private LitemallAccountBookService litemallAccountBookService;
    @Autowired
    private PosPushSender posPushSender;

    @Autowired
    private LitemallUserService litemallUserService;

    @Autowired
    private LumierePayMemberService lumierePayMemberService;

    @Autowired
    private LumierePayMemberUserService lumierePayMemberUserService;

    @Autowired
    private LumierelLevelMemberService lumierelLevelMemberService;

    @Autowired
    private LumiereLevelMemberPointService lumiereLevelMemberPointService;

    @Autowired
    private LitemallIntegralLogService integralLogService;

    @Autowired
    private LitemallCouponUserService litemallCouponUserService;

    @Autowired
    private LumiereMemberWelfareCouponService lumiereMemberWelfareCouponService;

    @Autowired
    private LitemallCouponService litemallCouponService;


    @Autowired
    private LumiereMemberWelfareSubscribeService lumiereMemberWelfareSubscribeService;

    @Autowired
    private LumiereSubscribeUserService lumiereSubscribeUserService;

    @Autowired
    private LitemallGiftCardService litemallGiftCardService;

    @Autowired
    private LitemallGiftCardUserService litemallGiftCardUserService;

    @Autowired
    private LumiereSubscribeRuleService lumiereSubscribeRuleService;

    @Autowired
    private LitemallShopRegionService shopRegionService;

    @Autowired
    private LitemallRegionService regionService;

    @Autowired
    private LumiereCouponUserService lumiereCouponUserService;

    @Autowired
    private LumiereCouponStrategyService lumiereCouponStrategyService;


    @Override
    public Object getPayment(Integer userId, Integer orderId, String successUrl, String cancelUrl,String message){
        LitemallOrder litemallOrder = orderService.findByUserAndId(userId, orderId);


        // 检测订单是否能够支付
        OrderHandleOption handleOption = OrderStatusUtil.build(litemallOrder);
        if (!handleOption.isPay()) {
            return ResponseUtil.fail(PaymentResponseCode.ORDER_INVALID_OPERATION, "订单不能支付");
        }
        BigDecimal total = litemallOrder.getActualPrice();
        BigDecimal tax = litemallOrder.getTaxPrice();
        BigDecimal shipping = litemallOrder.getFreightPrice();
        /*Amount amount = new Amount();
        amount.setCurrency(DefaultCurType.CAD.getType());
        amount.setTotal(String.format("%.2f", total));
        Details details = new Details();
        *//**
         * 退款金额
         *//*
        details.setFee(String.format("%.2f", total));
        *//**
         * 税费
         *//*

        details.setTax(String.format("%.2f", tax));
        *//**
         * 运费
         *//*
        details.setShipping(String.format("%.2f", shipping));

//        amount.setDetails(details);
        Transaction transaction = new Transaction();
        transaction.setDescription(litemallOrder.getDescription());
        transaction.setAmount(amount);

        List<Transaction> transactions = new ArrayList<>();
        transactions.add(transaction);

        Payer payer = new Payer();
        payer.setPaymentMethod(PaypalPaymentMethod.paypal.toString());

        Payment payment = new Payment();
        payment.setIntent(PaypalPaymentIntent.sale.toString());
        payment.setPayer(payer);
        payment.setTransactions(transactions);
        RedirectUrls redirectUrls = new RedirectUrls();
        redirectUrls.setCancelUrl(cancelUrl);
        redirectUrls.setReturnUrl(successUrl);
        payment.setRedirectUrls(redirectUrls);*/



        Amount amount = new Amount();
        amount.setCurrency(DefaultCurType.CAD.getType());
        amount.setTotal(String.format("%.2f", total));

        Transaction transaction = new Transaction();
        transaction.setDescription(litemallOrder.getDescription());
        transaction.setAmount(amount);


        List<Transaction> transactions = new ArrayList<>();
        transactions.add(transaction);

        Payer payer = new Payer();
        payer.setPaymentMethod(PaypalPaymentMethod.paypal.toString());

        Payment payment = new Payment();
        payment.setIntent(PaypalPaymentIntent.sale.toString());
        payment.setPayer(payer);
        payment.setTransactions(transactions);
        RedirectUrls redirectUrls = new RedirectUrls();
        redirectUrls.setCancelUrl(cancelUrl);
        redirectUrls.setReturnUrl(successUrl);
        payment.setRedirectUrls(redirectUrls);

        try {
            logger.debug("success url is " + redirectUrls.getReturnUrl());
            logger.debug("cancel url is " + redirectUrls.getCancelUrl());
            Payment rtn =  payment.create(apiContext);
            if(null == rtn.getId() || !PaypalPaymentState.created.toString().equals(rtn.getState())){
                return ResponseUtil.fail(PaymentResponseCode.ORDER_INVALID_OPERATION, "订单不能支付");
            }
            String paymentId = rtn.getId();
            //保存paymentId作为PayPal的商户订单号
            litemallOrder.setOutTradeNo(paymentId);
            int i = orderService.updateWithOptimisticLocker(litemallOrder);
            if (i == 0) {
                return ResponseUtil.updatedDateExpired();
            }
            //缓存paymentId用于后续模版通知

            LitemallUserFormid userFormid = new LitemallUserFormid();
            userFormid.setFormid(paymentId);
            userFormid.setIsprepay(true);
            userFormid.setUseamount(3);
            userFormid.setOpenid("");
            userFormid.setExpireTime(LocalDateTime.now().plusDays(7));
            formIdService.addUserFormid(userFormid);

            return rtn;
        } catch (PayPalRESTException e) {
            e.printStackTrace();
            return ResponseUtil.fail(PaymentResponseCode.ORDER_INVALID_OPERATION, "订单不能支付");
        }
    }
    @Override
    public Object executePayment(String paymentId, String payerId) throws PayPalRESTException{
        Payment payment = new Payment();
        payment.setId(paymentId);
        PaymentExecution paymentExecute = new PaymentExecution();
        paymentExecute.setPayerId(payerId);
         Payment rtn = payment.execute(apiContext, paymentExecute);

        // 交易号
        String transationId = rtn.getTransactions().get(0).getRelatedResources().get(0).getSale().getId();
        if(rtn.getState().equals("approved")){
            LitemallOrder order = orderService.findByOutTradeNo(paymentId);
            List<Transaction> transactions = rtn.getTransactions();
            BigDecimal totalFee = new BigDecimal(0.00);
            if(transactions != null){
                for(Transaction transaction: transactions){
                    String total = transaction.getAmount().getTotal();
                    BigDecimal b = new BigDecimal(total);
                    b.setScale(2, BigDecimal.ROUND_DOWN);
                    totalFee = totalFee.add(b);
                }
            }
            if (order == null) {
                return ResponseUtil.fail(PaymentResponseCode.ORDER_UNKNOWN, "订单不存在");
            }

            // 检查这个订单是否已经处理过
            if (OrderStatusUtil.isPayStatus(order) || order.getPayId() != null) {
                return ResponseUtil.fail(PaymentResponseCode.PAYMENT_FAIL, order.getOrderSn() + "The order has been processed successfully!!");
            }

            // 检查支付订单金额
            if (!totalFee.toString().equals(order.getActualPrice().toString())) {
                return ResponseUtil.fail(PaymentResponseCode.PAYMENT_FAIL, order.getOrderSn() + " : Payment amount does not meet totalFee=" + totalFee);
            }

            order.setPayType(Constants.ORDER_PAY_TYPE_PAYPAL);
            order.setCurrency(DefaultCurType.CAD.getType());
            order.setTransationId(transationId);        //交易号，退款时需要用到
            order.setPayId(payment.getId());            //付款编号，获取详情是需要用到？
            order.setPayTime(LocalDateTime.now());
            //order.setOrderStatus(OrderUtil.STATUS_PAY);
            order.setOrderStatus(Constants.ORDER_STATUS_ONGOING);
            order.setMadeStatus(Constants.ORDER_MADE_STATUS_NEW);//更新订单状态为待制作
            orderService.updateById(order);
            /*if (orderService.updateWithOptimisticLocker(order) == 0) {
                // 这里可能存在这样一个问题，用户支付和系统自动取消订单发生在同时
                // 如果数据库首先因为系统自动取消订单而更新了订单状态；
                // 此时用户支付完成回调这里也要更新数据库，而由于乐观锁机制这里的更新会失败
                // 因此，这里会重新读取数据库检查状态是否是订单自动取消，如果是则更新成支付状态。
                order = orderService.findBySn(order.getOrderSn());
                int updated = 0;
                if (OrderStatusUtil.isCancelStatus(order)) {
                    order.setPayTime(LocalDateTime.now());
//                    order.setOrderStatus(OrderUtil.STATUS_PAY);
                    order.setOrderStatus(Constants.ORDER_STATUS_ONGOING);
                    order.setMadeStatus(Constants.ORDER_MADE_STATUS_NEW);//更新订单状态为待制作
                    updated = orderService.updateWithOptimisticLocker(order);
                }

                // 如果updated是0，那么数据库更新失败
                if (updated == 0) {
                    return ResponseUtil.updatedDateExpired();
                }
            }*/

            /**
            //用户增加积分
            List<LitemallOrderGoods> orderGoods = litemallOrderGoodsService.queryByOid(order.getId());
            BigDecimal giveAwayPoints = new BigDecimal(0.00);
            for(LitemallOrderGoods item : orderGoods){
                LitemallGoods goods = goodsService.findById(item.getId());
                if(goods.getGiveAwayPoints() != null){
                    giveAwayPoints = giveAwayPoints.add(goods.getGiveAwayPoints().multiply(new BigDecimal(item.getNumber())));
                }
            }
            if(giveAwayPoints.compareTo(new BigDecimal(0.00)) > 0){
                LitemallUser user = userService.findById(order.getUserId());
                if(user != null){
                    LitemallUser update = new LitemallUser();
                    update.setId(order.getUserId());
                    update.setPoints(user.getPoints().add(giveAwayPoints));
                    userService.updateById(update);
                }

            }
             */

            //添加收款记录
        	LitemallAccountBookFormDto form = new LitemallAccountBookFormDto();
        	Integer shopId = order.getShopId();
        	form.setShopId(shopId);
        	form.setRecordType(0);
        	form.setRecordDate(LocalDateTime.now());
        	form.setAmount(order.getActualPrice());
        	form.setRemark("app order");
        	form.setSourceType(Constants.BOOK_SOURCE_TYPE_ORDER);
        	litemallAccountBookService.create(shopId, form);

            //TODO 发送邮件和短信通知，这里采用异步发送
            // 订单支付成功以后，会发送短信给用户，以及发送邮件给管理员
//            notifyService.notifyMail("新订单通知", order.toString());
//            awsNotifyService.noticeMail("新订单通知", order.toString(), order.toString(),getSendTo(order.getShopId()));

            //发送已支付订单到pos系统，门店开始制作商品
            //noticeHelper.noticeShop(Constants.MSG_TYPE_ORDER, order.getId().toString(), order.getShopId());
            // 这里微信的短信平台对参数长度有限制，所以将订单号只截取后6位
//            notifyService.notifySmsTemplateSync(order.getMobile(), NotifyType.PAY_SUCCEED, new String[]{order.getOrderSn().substring(8, 14)});
//            noticeHelper.noticeUser(Constants.MSG_TYPE_ORDER, order.getOrderSn() + "支付成功", order.getUserId());
            //推送厨房端
        	//posPushSender.pushAll(order.getShopId(), Constants.ORDER_PUSH_TYPE_PAID, null);
//            noticeHelper.noticeUser( Constants.MSG_TYPE_ORDER,"order paid successed", ""+, userId, giftCard);
            noticeHelper.noticeUser(Constants.MSG_TYPE_ORDER,"order payment", order.getOrderSn()+"order payment success", order.getUserId(), order);

            return rtn;
        }else{
            return ResponseUtil.fail(PaymentResponseCode.PAYMENT_FAIL, "支付失败");
        }
    }

    /**
     *
     * @param orderId
     * @return  false:退款失败； true:退款成功
     */
    @Override
    public boolean refund(Integer orderId) {
        LitemallOrder order = orderService.findById(orderId);

        RefundRequest refund = new RefundRequest();
        Amount amount = new Amount();
        amount.setCurrency(order.getCurrency());
        amount.setTotal(String.format("%.2f", order.getActualPrice()));
        refund.setAmount(amount);
        refund.setReason(order.getDescription());

        try {
            if(StringUtils.isEmpty(order.getTransationId())) {
                //注意这段代码，获取saleId
                Payment payment = Payment.get(apiContext, order.getPayId());
                Transaction transaction = payment.getTransactions().get(0);
                RelatedResources resources = transaction.getRelatedResources().get(0);
                String id = resources.getSale().getId();
                order.setTransationId(id);
            }

            Sale sale = new Sale();
            sale.setId(order.getTransationId());
            DetailedRefund res = sale.refund(apiContext, refund);
            if(res.getState().equals(PaypalPaymentState.completed.toString())){
                //是否使用优惠券，如果有，就返还优惠券
                List<LitemallCouponUser> couponUsers = litemallCouponUserService.queryByOrderId(order.getId());
                if(couponUsers.size() > 0 && couponUsers.get(0) != null){
                    couponUsers.get(0).setStatus(CouponUserConstant.STATUS_USABLE);
                    couponUsers.get(0).setUsedTime(null);
                    litemallCouponUserService.update(couponUsers.get(0));
                }

                return true;
            }
            return false;
        } catch (PayPalRESTException e) {
            e.printStackTrace();
            return false;
        }
    }

    private String getSendTo(Integer shopId){
        List<LitemallAdmin> admins = litemallAdminService.findByShopId(shopId);
        Optional<LitemallAdmin> rtn = admins.stream().filter(admin -> {
            return Arrays.asList(admin.getRoleIds()).contains(Constants.SHOPKEEPER_ROLE_ID);
        }).findFirst();
        if(rtn != null){
            return StringUtils.isEmpty(rtn.get().getEmail())?"":rtn.get().getEmail();
        }
        return "";
    }


    public  BigDecimal presentPoint(Integer orderId,Integer consumptionId){
        LitemallOrder order =  orderService.findById(orderId);
        Integer cityRegionId = getShopRegionId(order.getShopId());
        if(order != null){
            Integer userId = order.getUserId();
            LitemallUser user = litemallUserService.findById(userId);

            if(user != null){
                Byte userLevel = user.getUserLevel();
                //等级会员
                BigDecimal obtainPoint = BigDecimal.ZERO;

                //付费会员赠送积分   判断是否过期
                List<LumierePayMemberUser> payMemberUsers = lumierePayMemberUserService.listUsers(userId,null);
                for (int i = 0; i < payMemberUsers.size(); i++) {
                    //判断是否过期
                    if(payMemberUsers.get(i).getEndTime().compareTo(LocalDateTime.now()) > 0){
                        LumierePayMember payMember = lumierePayMemberService.findById(payMemberUsers.get(i).getPayMemberId());

                        boolean flag = false;
                        if(payMember.getShopIds() != null){
                            for (int j = 0; j < payMember.getShopIds().length; j++) {
                                if (payMember.getShopIds()[j].equals(cityRegionId)) {
                                    flag = true;
                                    break;
                                }
                            }
                        }else{
                            flag =  true;
                        }

                        if(payMember.getPointRatio() != null && payMember.getPointRatio() != 0 && flag){
                            if(obtainPoint.compareTo(BigDecimal.ZERO) == 0){
                                obtainPoint = order.getActualPrice().multiply(new BigDecimal(payMember.getPointRatio()));
                            }else if(obtainPoint.compareTo(order.getActualPrice().multiply(new BigDecimal(payMember.getPointRatio()))) < 0){
                                obtainPoint = order.getActualPrice().multiply(new BigDecimal(payMember.getPointRatio()));
                            }
                        }
                    }
                }

                if(userLevel.intValue()!=0){
                    LumiereLevelMember levelMember =  lumierelLevelMemberService.findById(userLevel.intValue());
                    if(levelMember.getPointRatio() != null && levelMember.getPointRatio() != 0 ){
                        if(obtainPoint.compareTo(BigDecimal.ZERO) == 0){
                            obtainPoint = order.getActualPrice().multiply(new BigDecimal(levelMember.getPointRatio()));
                        }else if(obtainPoint.compareTo(order.getActualPrice().multiply(new BigDecimal(levelMember.getPointRatio()))) < 0){
                            obtainPoint = order.getActualPrice().multiply(new BigDecimal(levelMember.getPointRatio()));
                        }
                    }
                }
                //用户添加积分
                user.setPoints(canadaRoundup(new BigDecimal(user.getPoints().add(obtainPoint).intValue())));

                userService.updateById(user);

                //积分记录
                LitemallIntegralLog log = new LitemallIntegralLog();
                log.setUserId(userId);
                log.setType(Constants.INTEGRAL_LOG_TYPE_ADD);
                log.setPoints(user.getPoints());
                log.setChangePoints(obtainPoint);
                if(consumptionId != null){
                    log.setConsumptionId(consumptionId);
                }
                log.setOrderId(orderId);
                //添加 详细信息
                log.setUseType(8);
                log.setGoodsName(litemallOrderGoodsService.queryByOid(orderId).stream().map(litemallOrderGoods -> litemallOrderGoods.getGoodsName()).collect(Collectors.toList()));
                integralLogService.add(log);
                LitemallOrder update =  new LitemallOrder();
                update.setUserId(order.getUserId());
                update.setPoints(obtainPoint);
                update.setId(order.getId());
                orderService.updateByIdEx(update);

                return obtainPoint;
            }else{
                return new BigDecimal(-1);
            }
        }else{
            return new BigDecimal(-1);
        }
    }
    public BigDecimal canadaRoundup(BigDecimal price) {
        BigDecimal a = price.multiply(BigDecimal.TEN).setScale(1, BigDecimal.ROUND_HALF_UP);
        BigDecimal b = a.remainder(BigDecimal.ONE);
        if (b.compareTo(new BigDecimal(0.2).setScale(1, BigDecimal.ROUND_HALF_UP)) <= 0) {
            a = a.subtract(b);
        } else if (b.compareTo(new BigDecimal(0.7).setScale(1, BigDecimal.ROUND_HALF_UP)) <= 0) {
            a = a.subtract(b).add(new BigDecimal(0.5));
        } else {
            a = a.subtract(b).add(new BigDecimal(1));
        }

        a = a.divide(BigDecimal.TEN).setScale(2, BigDecimal.ROUND_HALF_UP);
        return a;
    }

    /**
     * 用户购买，等级会员升级
     */
    public void upgradeUserLevel(Integer orderId) {
        LitemallOrder order = orderService.findById(orderId);
        Integer userId = order.getUserId();
        LitemallUser user = litemallUserService.findById(userId);

        //用户当前等级
        LumiereLevelMember levelMember = lumierelLevelMemberService.findById(user.getUserLevel().intValue());

        /*LumiereLevelMemberExample example = new LumiereLevelMemberExample();
        example.or().andPidEqualTo(levelMember.getId());

        List<LumiereLevelMember> nexts = lumierelLevelMemberService.list(example);*/

        //记录用户的积分
        List<LumiereLevelMemberPoint> points = lumiereLevelMemberPointService.listByUserId(userId);
        LumiereLevelMember upgradMember = lumierelLevelMemberService.queryByPidInDel(user.getUserLevel().intValue());
        //向上升级，查找升级的等级没有被删除，且状态为启用
        while (upgradMember != null && (upgradMember.getDeleted() == true || upgradMember.getStatus().equals(MEMBER_STATUS_INUSE) == false)) {
            upgradMember = lumierelLevelMemberService.queryByPid(upgradMember.getId());
        }
        if (points.size() == 0) {
            LumiereLevelMemberPoint point = new LumiereLevelMemberPoint();
            point.setConsumptionMoney(order.getActualPrice());

            point.setStartTime(LocalDateTime.now());
            if (levelMember != null && levelMember.getExpiredDays() != 0) {
                //point.setEndTime(LocalDateTime.of(LocalDate.now(), LocalTime.MAX).plusDays(levelMember.getExpiredDays()));
                point.setEndTime(LocalDateTime.now().plusDays(levelMember.getExpiredDays()));
            }
            point.setUserId(userId);
            point.setAddTime(LocalDateTime.now());
            point.setUpdateTime(LocalDateTime.now());
            point.setConsumptionMoney(order.getActualPrice());
            point.setDeleted(false);


            point.setConsumptionPoints(new BigDecimal(0.00).setScale(2,BigDecimal.ROUND_HALF_UP));

            //如果没有符合条件的就不升级
            if ( upgradMember != null &&  (upgradMember.getDeleted() == false && upgradMember.getStatus().equals(MEMBER_STATUS_INUSE) == true)) {
                if (levelMember.getUpgradeMoney() != null && levelMember.getUpgradeMoney().compareTo(order.getActualPrice()) <= 0) {
                    user.setUserLevel(upgradMember.getId().byteValue());
                    point.setConsumptionMoney(new BigDecimal(0));
                    //会员升级
                    userService.updateById(user);

                    //用户等级会员升级，赠送福利
                    LocalDateTime endT = upgradMember.getExpiredDays() != null ? LocalDateTime.now().plusDays(upgradMember.getExpiredDays()) : null;
                    welfareGift(upgradMember.getId(), null, null, userId, upgradMember, endT);
                    noticeHelper.noticeUser(Constants.MSG_TYPE_OTHER,
                            LitemallWXMembershipLevelConstants.WX_MEMBERSHIP_LEVEL_TITLE_NOTICEHELPER,
                            String.format(LitemallWXMembershipLevelConstants.WX_MEMBERSHIP_LEVEL_UPGRADE_NOTICEHELPER,upgradMember.getName()),userId,upgradMember);
                }
            }
            lumiereLevelMemberPointService.add(point);
        } else {
            //用户会员等级的变化
            LumiereLevelMemberPoint point = points.get(0);
            if ( upgradMember != null && (upgradMember.getDeleted() == false && upgradMember.getStatus().equals(MEMBER_STATUS_INUSE))) {
                if (levelMember.getUpgradeMoney() != null && levelMember.getUpgradeMoney().compareTo(order.getActualPrice().add(point.getConsumptionMoney())) <= 0) {
//                    LumiereLevelMemberExample ex2 = new LumiereLevelMemberExample();
//                    ex2.or().andPidEqualTo(user.getUserLevel().intValue());
//                    List<LumiereLevelMember> list = lumierelLevelMemberService.list(ex2);
                    user.setUserLevel(upgradMember.getId().byteValue());

                    userService.updateById(user);
//                     points.get(0).setConsumptionMoney(new BigDecimal(0));
                    //更改会员积分使用记录
                    if (upgradMember.getExpiredDays() != null && upgradMember.getExpiredDays() != 0) {
                        point.setStartTime(LocalDateTime.now());
                        point.setEndTime(LocalDateTime.now().plusDays(upgradMember.getExpiredDays()));
                        //point.setEndTime(LocalDateTime.of(LocalDate.now(), LocalTime.MAX).plusMonths(1));
                    } else {
                        point.setEndTime(point.getEndTime());
                    }


                    LocalDateTime endT = upgradMember.getExpiredDays() != null ? LocalDateTime.now().plusDays(upgradMember.getExpiredDays()) : null;
                    welfareGift(upgradMember.getId(), null, null, userId, upgradMember, endT);
                    noticeHelper.noticeUser(Constants.MSG_TYPE_OTHER,
                            LitemallWXMembershipLevelConstants.WX_MEMBERSHIP_LEVEL_TITLE_NOTICEHELPER,
                            String.format(LitemallWXMembershipLevelConstants.WX_MEMBERSHIP_LEVEL_UPGRADE_NOTICEHELPER,upgradMember.getName()),userId,upgradMember);
                    point.setConsumptionMoney(BigDecimal.ZERO);
                } else {
                    point.setConsumptionMoney(point.getConsumptionMoney().add(order.getActualPrice()));
                    point.setEndTime(point.getEndTime());
                }
                lumiereLevelMemberPointService.update(point);
            }
        }
    }

    public void welfareGift(Integer memberId, LitemallUser giveeUser,
                            String userName, Integer userId, LumiereLevelMember levelMember, LocalDateTime endT) {
        //新优惠券
        List<LumiereCouponStrategy> lumiereCouponStrategies = lumiereCouponStrategyService.list(Wrappers.lambdaQuery(LumiereCouponStrategy.class)
                .eq(LumiereCouponStrategy::getCouponType, 5)
                .eq(LumiereCouponStrategy::getStatus, 1)
                .eq(LumiereCouponStrategy::getDeleted, 0));
        lumiereCouponStrategies.stream().forEach(lumiereCouponStrategy->{
            for (Integer levelMemberId : lumiereCouponStrategy.getLevelMember()){
                if(levelMemberId.equals(memberId)){
                    for(int i=1;i<=(lumiereCouponStrategy.getReleasedQuantity()==null?1:lumiereCouponStrategy.getReleasedQuantity());i++){
                    long nextId = IdUtil.getSnowflake(2, 2).nextId();
                    LocalDateTime[] localDateTimes = AdminCouponDateUtil.calculateExpirationTime(lumiereCouponStrategy);
                    //发放券
                    LumiereCouponUser coupon = LumiereCouponUser.builder()
                            .userId(userId)
                            .strategyId(lumiereCouponStrategy.getId())
                            .couponId(lumiereCouponStrategy.getCouponId())
                            .userName(userName)
                            .startTime(localDateTimes[0])
                            .endTime(localDateTimes[1])
                            .code(String.valueOf(nextId))
                            .addTime(LocalDateTime.now())
                            .updateTime(LocalDateTime.now())
                            .deleted(false)
                            .build();
                    lumiereCouponUserService.save(coupon);
                }
            }}
        });


        //添加优惠券
        List<LumiereMemberWelfareCoupon> welfareCoupons = lumiereMemberWelfareCouponService.findByMemberId(memberId, (byte) 1);

        welfareCoupons.stream().forEach(welfareCoupon -> {
            Integer couponNum = welfareCoupon.getNumbers();
            LitemallCoupon coupon = litemallCouponService.findById(welfareCoupon.getCouponId());

            if (coupon != null) {
                LocalDateTime startT = coupon.getStartTime();
                LocalDateTime endTime = coupon.getEndTime();
                if(coupon.getTimeType().equals(0)){
                    startT = LocalDateTime.now();
                    endTime = startT.plusDays(coupon.getDays());
                }

                for (Integer i = 0; i < couponNum; i++) {
                    LitemallCouponUser litemallCouponUser = new LitemallCouponUser();
                    litemallCouponUser.setStartTime(startT);
                    litemallCouponUser.setEndTime(endTime);
                    litemallCouponUser.setStatus((short) 0);
                    litemallCouponUser.setCouponId(coupon.getId());
                    litemallCouponUser.setAddTime(LocalDateTime.now());
                    litemallCouponUser.setUpdateTime(LocalDateTime.now());
                    litemallCouponUser.setDeleted(false);
                    litemallCouponUser.setUserId(giveeUser != null ? giveeUser.getId() : userId);
                    litemallCouponUser.setUserName(userName);
                    litemallCouponUserService.add(litemallCouponUser);
                }
            }
        });

        //添加用户订阅
        List<LumiereMemberWelfareSubscribe> welfareSubscribes = lumiereMemberWelfareSubscribeService.findByMemberId(memberId, (byte) 1);

        welfareSubscribes.stream().forEach(welfareSubscribe -> {
            Integer[] selectRuleIds = welfareSubscribe.getSubscribeRuleIds();
            LumiereSubscribeUser subscribeUser = addSubscribeUser(userId, welfareSubscribe.getSubscribeId(), selectRuleIds, endT, userName, giveeUser);
            lumiereSubscribeUserService.add(subscribeUser);
        });


        //添加礼物卡
        if (levelMember.getGiftCardIds() != null) {
            Integer[] giftCardIds = levelMember.getGiftCardIds();
            for (int i = 0; i < giftCardIds.length; i++) {
                LitemallGiftCard litemallGiftCard = litemallGiftCardService.findById(giftCardIds[i]);
                if (litemallGiftCard != null) {
                    LitemallGiftCardUser giftCardUser = new LitemallGiftCardUser();
                    giftCardUser.setIsDefault(0);

                    String cardNumber = GeneratorUtil.cardNumberGenerator("00", userId);
                    LitemallGiftCardUser cardUser = litemallGiftCardUserService.findByNumber(cardNumber);
                    while (cardUser != null) {
                        cardNumber = GeneratorUtil.cardNumberGenerator("00", userId);
                        cardUser = litemallGiftCardUserService.findByNumber(cardNumber);
                    }
                    giftCardUser.setCardNumber(cardNumber);
                    giftCardUser.setUserId(giveeUser != null ? giveeUser.getId() : userId);
                    giftCardUser.setAmount(BigDecimal.ZERO);
                    giftCardUser.setStatus(0);
                    giftCardUser.setDeleted(false);
                    giftCardUser.setAddTime(LocalDateTime.now());
                    giftCardUser.setUpdateTime(LocalDateTime.now());
                    giftCardUser.setGiftCardId(giftCardIds[i]);
                    litemallGiftCardUserService.add(giftCardUser);
                }
            }
        }

    }

    public LumiereSubscribeUser addSubscribeUser(Integer userId, Integer subscribeId, Integer[] selectRuleIds,
                                                 LocalDateTime endT, String givee, LitemallUser giveeUser) {

        LitemallUser user = litemallUserService.findById(userId);

        LumiereSubscribeUser lumiereSubscribeUser = new LumiereSubscribeUser();
        lumiereSubscribeUser.setPurchaserId(userId);
        if (lumiereSubscribeUser.getUserId() == null) {
            lumiereSubscribeUser.setUserId(giveeUser != null ? giveeUser.getId() : userId);
        }

        LumiereSubscribeRule rule = lumiereSubscribeRuleService.findById(selectRuleIds[0]);

        lumiereSubscribeUser.setSubscribeId(subscribeId);

        lumiereSubscribeUser.setStatus(Constants.SUBSCRIBE_USER_MEMBER_NOT_CONFIRM);

        lumiereSubscribeUser.setAutoSub(false);

        lumiereSubscribeUser.setPurchaserId(giveeUser != null ? giveeUser.getId() : userId);

        lumiereSubscribeUser.setUserName(giveeUser != null ? giveeUser.getUsername() : user != null ? user.getUsername() : null);

        lumiereSubscribeUser.setPrice(BigDecimal.ZERO);

        lumiereSubscribeUser.setStartTime(LocalDateTime.now());

        if(rule != null) {
            if (rule.getRuleType().equals((byte) 1)) {
                lumiereSubscribeUser.setEndTime(LocalDateTime.now().plusWeeks(1));
            } else if (rule.getRuleType().equals((byte) 2)) {
                lumiereSubscribeUser.setEndTime(LocalDateTime.now().plusMonths(1));
            } else {
                lumiereSubscribeUser.setEndTime(LocalDateTime.now().plusYears(1));
            }
        }
        lumiereSubscribeUser.setRuleId(selectRuleIds[0]);

        return lumiereSubscribeUser;
    }

    private Integer getShopRegionId(Integer shopId) {
        List<LitemallShopRegion> litemallShopRegions = shopRegionService.queryByShopId(shopId);
        if (!CollectionUtils.isEmpty(litemallShopRegions)) {
            for (LitemallShopRegion litemallShopRegion : litemallShopRegions) {
                LitemallRegion litemallRegion = regionService.findById(litemallShopRegion.getRegionId());
                if (Constants.REGION_TYPE_CITY == litemallRegion.getType()) {
                    return litemallShopRegion.getRegionId();
                }
            }
        }
        return null;
    }
}
